#include "statsxx/preprocess/Preprocessor.hpp"

// STL
#include <algorithm>                  // std::minmax_element()
#include <vector>                     // std::vector<>

// jScience
#include "jScience/linalg/Matrix.hpp" // Matrix<>

// stats++
#include "statsxx/statistics.hpp"     // statistics::mean(), ::stddev()


//
// DESC: Initializes the preprocessor.
//
inline void Preprocessor::initialize(
                                     const Matrix<double> &X
                                     )
{
    this->X_init = X;

    // note: precalculating these (potentially) involves additional calculations up front, but avoids repeated if() checks during successive calls (for scaling data, etc.)
    for( int j = 0; j < X.get_size(1); ++j )
    {
        std::vector<double> x;

        for( int i = 0; i < X.get_size(0); ++i )
        {
            x.push_back(X(i,j));
        }

        auto result = std::minmax_element(x.begin(), x.end());

        this->x_min.push_back( *result.first );
        this->x_max.push_back( *result.second );
        this->x_max_minus_min.push_back( *result.second - *result.first );
        this->x_mean.push_back( statistics::mean(x) );
        this->x_s.push_back( statistics::stddev(x) );
    }

    this->init = true;
}


